package com.sergio.accounting.controller;

import com.sergio.accounting.dto.ApiResponse;
import com.sergio.accounting.entity.Category;
import com.sergio.accounting.repository.CategoryRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * 分类控制器
 */
@Slf4j
@RestController
@RequestMapping("/categories")
@RequiredArgsConstructor
@CrossOrigin
public class CategoryController {

    private final CategoryRepository categoryRepository;

    /**
     * 获取所有分类
     */
    @GetMapping
    public ApiResponse<List<Category>> getAllCategories() {
        try {
            List<Category> categories = categoryRepository.findByEnabledOrderBySortOrderAsc(true);
            return ApiResponse.success(categories);
        } catch (Exception e) {
            log.error("获取分类列表失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 根据类型获取分类
     */
    @GetMapping("/type/{type}")
    public ApiResponse<List<Category>> getCategoriesByType(@PathVariable String type) {
        try {
            Category.CategoryType categoryType = Category.CategoryType.valueOf(type.toUpperCase());
            List<Category> categories = categoryRepository.findByTypeAndEnabledOrderBySortOrderAsc(categoryType, true);
            return ApiResponse.success(categories);
        } catch (Exception e) {
            log.error("根据类型获取分类失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 根据ID获取分类
     */
    @GetMapping("/{id}")
    public ApiResponse<Category> getCategoryById(@PathVariable Long id) {
        try {
            Category category = categoryRepository.findById(id)
                    .orElseThrow(() -> new RuntimeException("分类不存在"));
            return ApiResponse.success(category);
        } catch (Exception e) {
            log.error("获取分类失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 添加分类
     */
    @PostMapping
    public ApiResponse<Category> addCategory(@RequestBody @Valid CategoryRequest request) {
        try {
            // 检查分类名称是否已存在
            if (categoryRepository.existsByName(request.getName())) {
                return ApiResponse.error("分类名称已存在");
            }

            Category category = new Category();
            category.setName(request.getName());
            category.setDescription(request.getDescription());
            category.setType(Category.CategoryType.valueOf(request.getType().toUpperCase()));
            category.setIcon(request.getIcon());
            category.setSortOrder(request.getSortOrder() != null ? request.getSortOrder() : 0);
            category.setEnabled(true);

            Category savedCategory = categoryRepository.save(category);
            log.info("分类添加成功: {}", request.getName());
            return ApiResponse.success("添加成功", savedCategory);
        } catch (Exception e) {
            log.error("添加分类失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 更新分类
     */
    @PutMapping("/{id}")
    public ApiResponse<Category> updateCategory(@PathVariable Long id,
                                             @RequestBody @Valid CategoryRequest request) {
        try {
            Category category = categoryRepository.findById(id)
                    .orElseThrow(() -> new RuntimeException("分类不存在"));

            // 检查分类名称是否被其他分类使用
            if (!category.getName().equals(request.getName()) && 
                categoryRepository.existsByName(request.getName())) {
                return ApiResponse.error("分类名称已存在");
            }

            category.setName(request.getName());
            category.setDescription(request.getDescription());
            category.setType(Category.CategoryType.valueOf(request.getType().toUpperCase()));
            category.setIcon(request.getIcon());
            if (request.getSortOrder() != null) {
                category.setSortOrder(request.getSortOrder());
            }

            Category updatedCategory = categoryRepository.save(category);
            log.info("分类更新成功: {}", request.getName());
            return ApiResponse.success("更新成功", updatedCategory);
        } catch (Exception e) {
            log.error("更新分类失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 删除分类
     */
    @DeleteMapping("/{id}")
    public ApiResponse<String> deleteCategory(@PathVariable Long id) {
        try {
            Category category = categoryRepository.findById(id)
                    .orElseThrow(() -> new RuntimeException("分类不存在"));

            // 软删除，设置enabled为false
            category.setEnabled(false);
            categoryRepository.save(category);

            log.info("分类删除成功: {}", category.getName());
            return ApiResponse.success("删除成功");
        } catch (Exception e) {
            log.error("删除分类失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    /**
     * 启用/禁用分类
     */
    @PutMapping("/{id}/toggle")
    public ApiResponse<Category> toggleCategory(@PathVariable Long id) {
        try {
            Category category = categoryRepository.findById(id)
                    .orElseThrow(() -> new RuntimeException("分类不存在"));

            category.setEnabled(!category.getEnabled());
            Category updatedCategory = categoryRepository.save(category);

            String status = updatedCategory.getEnabled() ? "启用" : "禁用";
            log.info("分类{}成功: {}", status, category.getName());
            return ApiResponse.success(status + "成功", updatedCategory);
        } catch (Exception e) {
            log.error("切换分类状态失败: {}", e.getMessage());
            return ApiResponse.error(e.getMessage());
        }
    }

    // 请求DTO类
    public static class CategoryRequest {
        private String name;
        private String description;
        private String type;
        private String icon;
        private Integer sortOrder;

        // Getters and Setters
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        public String getIcon() { return icon; }
        public void setIcon(String icon) { this.icon = icon; }
        public Integer getSortOrder() { return sortOrder; }
        public void setSortOrder(Integer sortOrder) { this.sortOrder = sortOrder; }
    }
}
